<script>
import { getNodeKey } from './model/util'

export default {
  name: 'OkrTreeNode',
  components: {
    NodeContent: {
      props: {
        node: {
          required: true,
        },
      },
      render(h) {
        const parent = this.$parent
        if (parent.$props.renderContent) {
          return parent.$props.renderContent(h, this.node)
        }
        else {
          return this.$slots.default(this.node)
        }
      },
    },
    // 渲染展开节点的样式
    NodeBtnContent: {
      props: {
        node: {
          required: true,
        },
      },
      render(h) {
        const parent = this.$parent
        if (parent.$props.nodeBtnContent) {
          return parent.$props.nodeBtnContent(h, this.node)
        }
        else {
          if (this.$slots.default) {
            return this.$slots.default(this.node)
          }
        }
      },
    },
  },
  props: {
    props: {},
    node: {
      default() {
        return {
          level: 0,
          childNodes: [],
          leftExpanded: false,
          expanded: false,
        }
      },
    },
    root: {
      default() {
        return {}
      },
    },
    // 子节点是否可折叠
    showCollapsable: {
      type: Boolean,
      default: false,
    },
    // 判断是否是左子树的节点，样式需要改
    isLeftChildNode: {
      type: Boolean,
      default: false,
    },
    // 树节点的内容区的渲染 Function
    renderContent: Function,
    // 展开节点的内容渲染 Function
    nodeBtnContent: Function,
    // 显示节点数
    showNodeNum: Boolean,
    // 树节点区域的宽度
    labelWidth: [String, Number],
    // 树节点区域的高度
    labelHeight: [String, Number],
    // 用来控制选择节点的字段名
    selectedKey: String,
    // 每个树节点用来作为唯一标识的属性，整棵树应该是唯一的
    nodeKey: String,
  },
  data() {
    return {
      // node 的展开状态
      expanded: false,
      tree: null,
    }
  },
  computed: {
    isLeaf() {
      if (this.node.level === 1) {
        if (this.leftChildNodes.length == 0 && this.node.childNodes.length == 0) {
          return true
        }
        else {
          return false
        }
      }
      else {
        return this.node.isLeaf
      }
    },
    leftChildNodes() {
      if (this.tree && this.tree.store.onlyBothTree) {
        if (this.isLeftChildNode) {
          return this.node.childNodes
        }
        else {
          return this.node.leftChildNodes
        }
      }
      return []
    },
    animateName() {
      if (this.tree && this.tree.store.animate) {
        return this.tree.store.animateName
      }
      return ''
    },
    animateDuration() {
      if (this.tree && this.tree.store.animate) {
        return this.tree.store.animateDuration
      }
      return 0
    },
    // 是否显示展开按钮
    showNodeBtn() {
      if (this.isLeftChildNode) {
        return (
          (this.tree && this.tree.store.direction === 'horizontal'
          && this.showCollapsable
          && this.leftChildNodes.length > 0) || this.level === 1
        )
      }
      return (
        this.showCollapsable
        && this.node.childNodes
        && this.node.childNodes.length > 0
      )
    },
    showNodeLeftBtn() {
      return (
        (this.tree && this.tree.store.direction === 'horizontal'
        && this.showCollapsable
        && this.leftChildNodes.length > 0)
      )
    },
    // 节点的宽度
    computeLabelStyle() {
      let { labelWidth = 'auto', labelHeight = 'auto' } = this
      if (typeof labelWidth === 'number') {
        labelWidth = `${labelWidth}px`
      }
      if (typeof labelHeight === 'number') {
        labelHeight = `${labelHeight}px`
      }
      return {
        width: labelWidth,
        height: labelHeight,
      }
    },
    computeLabelClass() {
      const clsArr = []
      if (this.tree) {
        const store = this.tree.store
        if (store.labelClassName) {
          if (typeof store.labelClassName === 'function') {
            clsArr.push(store.labelClassName(this.node))
          }
          else {
            clsArr.push(store.labelClassName)
          }
        }
        if (store.currentLableClassName && this.node.isCurrent) {
          if (typeof store.currentLableClassName === 'function') {
            clsArr.push(store.currentLableClassName(this.node))
          }
          else {
            clsArr.push(store.currentLableClassName)
          }
        }
        if (this.node.isCurrent) {
          clsArr.push('is-current')
        }
      }
      return clsArr
    },
    computNodeStyle() {
      return {
        display: this.node.expanded ? '' : 'none',
      }
    },
    computLeftNodeStyle() {
      return {
        display: this.node.leftExpanded ? '' : 'none',
      }
    },
    // 是否显示左子数
    showLeftChildNode() {
      return (
        this.tree && this.tree.onlyBothTree
        && this.tree.store.direction === 'horizontal'
        && this.leftChildNodes
        && this.leftChildNodes.length > 0
      )
    },
  },
  watch: {
    'node.expanded': function (val) {
      // this.$nextTick(() => this.expanded = val);
    },
    'node.leftExpanded': function (val) {
      // this.$nextTick(() => this.expanded = val);
    },
  },
  created() {
    const parent = this.$parent
    if (parent.isTree) {
      this.tree = parent
    }
    else {
      this.tree = parent.tree
    }

    const tree = this.tree
    if (!tree) {
      console.warn('Can not find node\'s tree.')
    }
  },
  methods: {
    getNodeKey(node) {
      return getNodeKey(this.nodeKey, node.data)
    },
    handleNodeClick() {
      const store = this.tree.store
      store.setCurrentNode(this.node)
      this.tree.$emit('node-click', this.node.data, this.node, this)
    },
    handleBtnClick(isLeft) {
      isLeft = isLeft === 'left'
      if (this.tree) {
        const store = this.tree.store
        // 表示是OKR飞书模式
        if (store.onlyBothTree) {
          if (isLeft) {
            if (this.node.leftExpanded) {
              this.node.leftExpanded = false
              this.tree.$emit('node-collapse', this.node.data, this.node, this)
            }
            else {
              this.node.leftExpanded = true
              this.tree.$emit('node-expand', this.node.data, this.node, this)
            }
            return
          }
        }
        if (this.node.expanded) {
          this.node.collapse()
          this.tree.$emit('node-collapse', this.node.data, this.node, this)
        }
        else {
          this.node.expand()
          this.tree.$emit('node-expand', this.node.data, this.node, this)
        }
      }
    },
    handleContextMenu(event) {
      if (
        this.tree._events['node-contextmenu']
        && this.tree._events['node-contextmenu'].length > 0
      ) {
        event.stopPropagation()
        event.preventDefault()
      }
      this.tree.$emit(
        'node-contextmenu',
        event,
        this.node.data,
        this.node,
        this,
      )
    },
  },
}
</script>

<template>
  <div
    v-if="node.visible"
    class="org-chart-node"
    :style="{
      '--node-color': node.data.color,
      '--parent-node-color': node.data.parentColor,
    }"
    :class="[{
      'collapsed': !node.leftExpanded || !node.expanded,
      'is-leaf': isLeaf,
      'is-current': node.isCurrent,
      'is-left-child-node': isLeftChildNode,
      'is-not-child': node.level === 1 && node.childNodes.length <= 0 && leftChildNodes.length <= 0,
      'only-both-tree-node': node.level === 1 && tree.store.onlyBothTree,
    }]"
    @contextmenu="$event => handleContextMenu($event)"
  >
    <div
      v-if="showLeftChildNode"
      v-show="node.leftExpanded"
      class="org-chart-node-left-children"
    >
      <OkrTreeNode
        v-for="child in leftChildNodes"
        :key="getNodeKey(child)"
        :show-collapsable="showCollapsable"
        :node="child"
        :label-width="labelWidth"
        :label-height="labelHeight"
        :render-content="renderContent"
        :node-btn-content="nodeBtnContent"
        :selected-key="selectedKey"
        :node-key="nodeKey"
        :props="props"
        :show-node-num="showNodeNum"
        is-left-child-node
      />
    </div>
    <div
      class="org-chart-node-label"
      :class="{
        'is-root-label': node.level === 1,
        'is-not-right-child': node.level === 1 && node.childNodes.length <= 0,
        'is-not-left-child': node.level === 1 && leftChildNodes.length <= 0,
      }"
    >
      <div
        v-if="showNodeLeftBtn && leftChildNodes.length > 0"
        class="org-chart-node-left-btn"
        :class="{ expanded: node.leftExpanded }"
        @click="handleBtnClick('left')"
      >
        <template v-if="showNodeNum">
          <span v-if="!node.leftExpanded" class="org-chart-node-btn-text">
            {{ (node.level === 1 && leftChildNodes.length > 0) ? leftChildNodes.length : node.childNodes.length }}
          </span>
        </template>
        <NodeBtnContent v-else :node="node">
          <slot />
        </NodeBtnContent>
      </div>
      <div
        class="org-chart-node-label-inner"
        :class="computeLabelClass"
        :style="computeLabelStyle"
        @click="handleNodeClick"
      >
        <NodeContent :node="node">
          <slot>
            {{ node.label }}
          </slot>
        </NodeContent>
      </div>
      <div
        v-if="showNodeBtn && !isLeftChildNode"
        class="org-chart-node-btn"
        :class="{ expanded: node.expanded }"
        @click="handleBtnClick('right')"
      >
        <template v-if="showNodeNum">
          <span v-if="!node.expanded " class="org-chart-node-btn-text">
            {{ node.childNodes.length }}
          </span>
        </template>
        <NodeBtnContent v-else :node="node">
          <slot>
            <!-- <div class="org-chart-node-btn-text">10</div> -->
          </slot>
        </NodeBtnContent>
      </div>
    </div>
    <div
      v-if="!isLeftChildNode && node.childNodes && node.childNodes.length > 0"
      v-show="node.expanded"
      class="org-chart-node-children"
    >
      <OkrTreeNode
        v-for="child in node.childNodes"
        :key="getNodeKey(child)"
        :show-collapsable="showCollapsable"
        :node="child"
        :label-width="labelWidth"
        :label-height="labelHeight"
        :render-content="renderContent"
        :node-btn-content="nodeBtnContent"
        :selected-key="selectedKey"
        :node-key="nodeKey"
        :show-node-num="showNodeNum"
        :props="props"
      />
    </div>
  </div>
</template>
